package net.mycrub.bitwise.ocr.training;

import java.util.concurrent.Callable;

import net.mycrub.bitwise.core.Brain;
import net.mycrub.bitwise.core.IRetroAction;
import net.mycrub.bitwise.core.IRetroActionCallback;
import net.mycrub.bitwise.core.RetroActionType;
import net.mycrub.bitwise.core.util.Random;
import net.mycrub.bitwise.ocr.reading.Sampler;


public class DigitTrainerWorker implements Callable<int[]> {

    private RetroCallBack rcb = new RetroCallBack();
    
    private ListOfBrains brains;
    
    private int nbIterations;
    
    private Sampler sampler;
    private DigitSampleGenerator gen = new DigitSampleGenerator(20, 20);
    
    public DigitTrainerWorker(int nbIterations, Sampler sampler) {
        this.nbIterations = nbIterations;
        this.sampler = sampler;
    }

    public ListOfBrains getBrains() {
        return brains;
    }

    public void setBrains(ListOfBrains brains) {
        this.brains = brains;
    }

    private double[] makeSample(int digit) {
        return sampler.sample(gen.createImage(digit));
    }
    
    public int[] call() {
        int[] successes = new int[brains.list.size()];
        double[] input = null;

        for (int i = 0; i < nbIterations; i++) {
            int digit = (int)(Random.next() * 10);
            input = makeSample(digit);
            
            int b = 0;
            for (Brain brain : brains.list) {
                int out = whatIsTheDigit(brain.process(input, rcb));
                if (rcb.retroAction != null) {
                    if (out == digit) {
                        successes[b]++;
                        rcb.retroAction.process(RetroActionType.POSITIVE);
                    }
                    else {
                        rcb.retroAction.process(RetroActionType.NEGATIVE);
                    }
                }
                b++;
            }
        }
        
        return successes;
    }

    private int whatIsTheDigit(double[] output) {
        double max = 0;
        int digit = 0;
        for(int i = 0; i < output.length; i++) {
            if (i == 0 || output[i] > max) {
                max = output[i];
                digit = i;
            }
        }
        return digit;
    }
    
    private class RetroCallBack implements IRetroActionCallback {

        private IRetroAction retroAction;
        
        public void setRetroAction(IRetroAction retroAction) {
            this.retroAction = retroAction;
        }
        
    }

    
}
